Header file integer.hpp

namespace type_safe
{
    template <typename IntegerT, class Policy>
    class integer;
    
    template <class Integer>
    using make_signed_t = 'hidden';
    
    template <typename Integer>
    constexpr make_signed_t<Integer> make_signed(const Integer& i);
    
    template <typename Integer, class Policy>
    constexpr make_signed_t<integer<Integer, Policy>> make_signed(const integer<Integer, Policy>& i);
    
    template <class Integer>
    using make_unsigned_t = 'hidden';
    
    template <typename Integer>
    constexpr make_unsigned_t<Integer> make_unsigned(const Integer& i);
    
    template <typename Integer, class Policy>
    constexpr make_unsigned_t<integer<Integer, Policy>> make_unsigned(const integer<Integer, Policy>& i);
    
    template <typename SignedInteger>
    constexpr make_unsigned_t<SignedInteger> abs(const SignedInteger& i);
    
    template <typename SignedInteger, class Policy>
    constexpr make_unsigned_t<integer<SignedInteger, Policy>> abs(const integer<SignedInteger, Policy>& i);
    
    template <typename UnsignedInteger>
    constexpr UnsignedInteger abs(const UnsignedInteger& i);
    
    template <typename UnsignedInteger, class Policy>
    constexpr integer<UnsignedInteger, Policy> abs(const integer<UnsignedInteger, Policy>& i);
    
    //=== Comparison operators ===//
    template <typename A, typename B, class Policy>
    constexpr bool operator==(const integer<A, Policy>& a, const integer<B, Policy>& b);
    template <typename A, typename B, class Policy>
    constexpr bool operator==(const A& a, const integer<B, Policy>& b);
    template <typename A, class Policy, typename B>
    constexpr bool operator==(const integer<A, Policy>& a, const B& b);
    template <typename A, typename B, class Policy>
    constexpr bool operator!=(const integer<A, Policy>& a, const integer<B, Policy>& b);
    template <typename A, typename B, class Policy>
    constexpr bool operator!=(const A& a, const integer<B, Policy>& b);
    template <typename A, class Policy, typename B>
    constexpr bool operator!=(const integer<A, Policy>& a, const B& b);
    template <typename A, typename B, class Policy>
    constexpr bool operator<(const integer<A, Policy>& a, const integer<B, Policy>& b);
    template <typename A, typename B, class Policy>
    constexpr bool operator<(const A& a, const integer<B, Policy>& b);
    template <typename A, class Policy, typename B>
    constexpr bool operator<(const integer<A, Policy>& a, const B& b);
    template <typename A, typename B, class Policy>
    constexpr bool operator<=(const integer<A, Policy>& a, const integer<B, Policy>& b);
    template <typename A, typename B, class Policy>
    constexpr bool operator<=(const A& a, const integer<B, Policy>& b);
    template <typename A, class Policy, typename B>
    constexpr bool operator<=(const integer<A, Policy>& a, const B& b);
    template <typename A, typename B, class Policy>
    constexpr bool operator>(const integer<A, Policy>& a, const integer<B, Policy>& b);
    template <typename A, typename B, class Policy>
    constexpr bool operator>(const A& a, const integer<B, Policy>& b);
    template <typename A, class Policy, typename B>
    constexpr bool operator>(const integer<A, Policy>& a, const B& b);
    template <typename A, typename B, class Policy>
    constexpr bool operator>=(const integer<A, Policy>& a, const integer<B, Policy>& b);
    template <typename A, typename B, class Policy>
    constexpr bool operator>=(const A& a, const integer<B, Policy>& b);
    template <typename A, class Policy, typename B>
    constexpr bool operator>=(const integer<A, Policy>& a, const B& b);
    
    //=== Binary operations ===//
    template <typename A, typename B, class Policy>
    constexpr 'hidden' operator+(const integer<A, Policy>& a, const integer<B, Policy>& b);
    template <typename A, typename B, class Policy>
    constexpr 'hidden' operator-(const integer<A, Policy>& a, const integer<B, Policy>& b);
    template <typename A, typename B, class Policy>
    constexpr 'hidden' operator*(const integer<A, Policy>& a, const integer<B, Policy>& b);
    template <typename A, typename B, class Policy>
    constexpr 'hidden' operator/(const integer<A, Policy>& a, const integer<B, Policy>& b);
    template <typename A, typename B, class Policy>
    constexpr 'hidden' operator%(const integer<A, Policy>& a, const integer<B, Policy>& b);
    
    //=== Input/output ===//
    template <typename Char, class CharTraits, typename IntegerT, class Policy>
    std::basic_istream<Char, CharTraits>& operator>>(std::basic_istream<Char, CharTraits>& in, integer<IntegerT, Policy>& i);
    
    template <typename Char, class CharTraits, typename IntegerT, class Policy>
    std::basic_ostream<Char, CharTraits>& operator<<(std::basic_ostream<Char, CharTraits>& out, const integer<IntegerT, Policy>& i);
}

namespace std
{
}

Class template type_safe::integer

template <typename IntegerT, class Policy>
class integer
{
public:
    using integer_type = IntegerT;
    
    template <typename T>
    constexpr integer(const T& val);
    template <typename T>
    constexpr integer(const integer<T, Policy>& val);
    
    template <typename T>
    integer& operator=(const T& val);
    template <typename T>
    integer& operator=(const integer<T, Policy>& val);
    
    constexpr operator integer_type() const noexcept;
    constexpr integer_type get() const noexcept;
    
    constexpr integer operator+() const;
    
    constexpr integer operator-() const;
    
    integer& operator++();
    integer operator++(int);
    
    integer& operator--();
    integer operator--(int);
    
    //=== Compound assignment ===//
    template <typename T>
    integer& operator+=(const integer<T, Policy>& other);
    template <typename T>
    integer& operator+=(const T& other);
    template <typename T>
    integer& operator-=(const integer<T, Policy>& other);
    template <typename T>
    integer& operator-=(const T& other);
    template <typename T>
    integer& operator*=(const integer<T, Policy>& other);
    template <typename T>
    integer& operator*=(const T& other);
    template <typename T>
    integer& operator/=(const integer<T, Policy>& other);
    template <typename T>
    integer& operator/=(const T& other);
    template <typename T>
    integer& operator%=(const integer<T, Policy>& other);
    template <typename T>
    integer& operator%=(const T& other);
};

A type safe integer class.

This is a tiny, no overhead wrapper over a standard integer type. It behaves exactly like the built-in types except that narrowing conversions are not allowed. It also checks against unsigned under/overflow in debug mode and marks it as undefined for the optimizer otherwise.

A conversion is considered safe if both integer types have the same signedness and the size of the value being converted is less than or equal to the destination size.

Requires: IntegerT must be an integral type except bool and char (use signed char/unsigned char). \notes It intentionally does not provide the bitwise operations. \module types

Function template type_safe::integer::integer

(1)  template <typename T>
     constexpr integer(const T& val);

(2)  template <typename T>
     constexpr integer(const integer<T, Policy>& val);

Effects: Initializes it with the given value.

Notes: This function does not participate in overload resolution if T is not an integer type safely convertible to this type.

Assignment operator type_safe::integer::operator=

(1)  template <typename T>
     integer& operator=(const T& val);

(2)  template <typename T>
     integer& operator=(const integer<T, Policy>& val);

Effects: Assigns it with the given value.

Notes: This function does not participate in overload resolution if T is not an integer type safely convertible to this type.

Conversion operator type_safe::integer::operator integer_type

(1)  constexpr operator integer_type() const noexcept;

(2)  constexpr integer_type get() const noexcept;

Returns: The stored value as the native integer type.

Operator type_safe::integer::operator+

constexpr integer operator+() const;

Returns: The integer type unchanged.

Operator type_safe::integer::operator-

constexpr integer operator-() const;

Returns: The negative integer type.

Requires: The integer type must not be unsigned.

Operator type_safe::integer::operator++

(1)  integer& operator++();

(2)  integer operator++(int);

Effects: Increments the integer by one.

Operator type_safe::integer::operator--

(1)  integer& operator--();

(2)  integer operator--(int);

Effects: Decrements the integer by one.

Compound assignment

(1)  template <typename T>
     integer& operator+=(const integer<T, Policy>& other);

(2)  template <typename T>
     integer& operator+=(const T& other);

(3)  template <typename T>
     integer& operator-=(const integer<T, Policy>& other);

(4)  template <typename T>
     integer& operator-=(const T& other);

(5)  template <typename T>
     integer& operator*=(const integer<T, Policy>& other);

(6)  template <typename T>
     integer& operator*=(const T& other);

(7)  template <typename T>
     integer& operator/=(const integer<T, Policy>& other);

(8)  template <typename T>
     integer& operator/=(const T& other);

(9)  template <typename T>
     integer& operator%=(const integer<T, Policy>& other);

(10)  template <typename T>
     integer& operator%=(const T& other);

Effects: Same as the operation on the integer type.

Notes: These functions do not participate in overload resolution, if T is not an integer type safely convertible to this type.


Alias template type_safe::make_signed_t [types]

template <class Integer>
using make_signed_t = 'hidden';

std::make_signed for ts::integer.

Function template type_safe::make_signed [types]

template <typename Integer>
constexpr make_signed_t<Integer> make_signed(const Integer& i);

Returns: A new integer of the corresponding signed integer type.

Requires: The value of i must fit into signed type.

Function template type_safe::make_signed [types]

template <typename Integer, class Policy>
constexpr make_signed_t<integer<Integer, Policy>> make_signed(const integer<Integer, Policy>& i);

Returns: A new ts::integer of the corresponding signed integer type.

Requires: The value of i must fit into signed type.

Alias template type_safe::make_unsigned_t [types]

template <class Integer>
using make_unsigned_t = 'hidden';

std::make_unsigned for ts::integer.

Function template type_safe::make_unsigned [types]

template <typename Integer>
constexpr make_unsigned_t<Integer> make_unsigned(const Integer& i);

Returns: A new integer of the corresponding unsigned integer type.

Requires: The value of i must not be negative.

Function template type_safe::make_unsigned [types]

template <typename Integer, class Policy>
constexpr make_unsigned_t<integer<Integer, Policy>> make_unsigned(const integer<Integer, Policy>& i);

Returns: A new ts::integer of the corresponding unsigned integer type.

Requires: The value of i must not be negative.

Function template type_safe::abs [types]

template <typename SignedInteger>
constexpr make_unsigned_t<SignedInteger> abs(const SignedInteger& i);

Returns: The absolute value of a built-in signed integer. It will be changed to the unsigned return type as well.

Function template type_safe::abs [types]

template <typename SignedInteger, class Policy>
constexpr make_unsigned_t<integer<SignedInteger, Policy>> abs(const integer<SignedInteger, Policy>& i);

Returns: The absolute value of an ts::integer.

Function template type_safe::abs [types]

template <typename UnsignedInteger>
constexpr UnsignedInteger abs(const UnsignedInteger& i);

Returns: i unchanged.

Notes: This is an optimization of abs() for unsigned integer types.

Function template type_safe::abs [types]

template <typename UnsignedInteger, class Policy>
constexpr integer<UnsignedInteger, Policy> abs(const integer<UnsignedInteger, Policy>& i);

Returns: i unchanged.

Notes: This is an optimization of abs() for unsigned integer types.

Comparison operators [types]

(1)  template <typename A, typename B, class Policy>
     constexpr bool operator==(const integer<A, Policy>& a, const integer<B, Policy>& b);

(2)  template <typename A, typename B, class Policy>
     constexpr bool operator==(const A& a, const integer<B, Policy>& b);

(3)  template <typename A, class Policy, typename B>
     constexpr bool operator==(const integer<A, Policy>& a, const B& b);

(4)  template <typename A, typename B, class Policy>
     constexpr bool operator!=(const integer<A, Policy>& a, const integer<B, Policy>& b);

(5)  template <typename A, typename B, class Policy>
     constexpr bool operator!=(const A& a, const integer<B, Policy>& b);

(6)  template <typename A, class Policy, typename B>
     constexpr bool operator!=(const integer<A, Policy>& a, const B& b);

(7)  template <typename A, typename B, class Policy>
     constexpr bool operator<(const integer<A, Policy>& a, const integer<B, Policy>& b);

(8)  template <typename A, typename B, class Policy>
     constexpr bool operator<(const A& a, const integer<B, Policy>& b);

(9)  template <typename A, class Policy, typename B>
     constexpr bool operator<(const integer<A, Policy>& a, const B& b);

(10)  template <typename A, typename B, class Policy>
     constexpr bool operator<=(const integer<A, Policy>& a, const integer<B, Policy>& b);

(11)  template <typename A, typename B, class Policy>
     constexpr bool operator<=(const A& a, const integer<B, Policy>& b);

(12)  template <typename A, class Policy, typename B>
     constexpr bool operator<=(const integer<A, Policy>& a, const B& b);

(13)  template <typename A, typename B, class Policy>
     constexpr bool operator>(const integer<A, Policy>& a, const integer<B, Policy>& b);

(14)  template <typename A, typename B, class Policy>
     constexpr bool operator>(const A& a, const integer<B, Policy>& b);

(15)  template <typename A, class Policy, typename B>
     constexpr bool operator>(const integer<A, Policy>& a, const B& b);

(16)  template <typename A, typename B, class Policy>
     constexpr bool operator>=(const integer<A, Policy>& a, const integer<B, Policy>& b);

(17)  template <typename A, typename B, class Policy>
     constexpr bool operator>=(const A& a, const integer<B, Policy>& b);

(18)  template <typename A, class Policy, typename B>
     constexpr bool operator>=(const integer<A, Policy>& a, const B& b);

Returns: The result of the comparison of the stored integer value in the ts::integer.

Notes: These functions do not participate in overload resolution unless A and B are both integer types.

Binary operations [types]

(1)  template <typename A, typename B, class Policy>
     constexpr 'hidden' operator+(const integer<A, Policy>& a, const integer<B, Policy>& b);

(2)  template <typename A, typename B, class Policy>
     constexpr 'hidden' operator-(const integer<A, Policy>& a, const integer<B, Policy>& b);

(3)  template <typename A, typename B, class Policy>
     constexpr 'hidden' operator*(const integer<A, Policy>& a, const integer<B, Policy>& b);

(4)  template <typename A, typename B, class Policy>
     constexpr 'hidden' operator/(const integer<A, Policy>& a, const integer<B, Policy>& b);

(5)  template <typename A, typename B, class Policy>
     constexpr 'hidden' operator%(const integer<A, Policy>& a, const integer<B, Policy>& b);

Returns: The result of the binary operation of the stored integer value in the ts::integer. The type is a ts::integer of the bigger integer type.

Notes: These functions do not participate in overload resolution, unless A and B are both integer types.

Input operator type_safe::operator>> [types]

template <typename Char, class CharTraits, typename IntegerT, class Policy>
std::basic_istream<Char, CharTraits>& operator>>(std::basic_istream<Char, CharTraits>& in, integer<IntegerT, Policy>& i);

Effects: Reads an integer from the std::istream and assigns it to the given ts::integer.

Output operator type_safe::operator<<

template <typename Char, class CharTraits, typename IntegerT, class Policy>
std::basic_ostream<Char, CharTraits>& operator<<(std::basic_ostream<Char, CharTraits>& out, const integer<IntegerT, Policy>& i);

Effects: Converts the given ts::integer to the underlying integer type and writes it to th std::ostream. \module types